﻿var net = require('net');
var url = require('url');
var http = require('http');
var crypto = require('crypto');
var dgram = require('dgram');
var fs = require('fs');
var publicPem = fs.readFileSync('cert.pem');
var CRC = {};
CRC._auchCRCHi = [
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
];
CRC._auchCRCLo = [
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40
];
var cccccc1 = {
    encrypt: 'tOdcFVMvX0Wf6zBjSCbCntD3DfcL4UhcvsJoGNt8JS9P8xHrPNI4QqjG22h54X7l',
    sig: '10d6a5d16b35e6210fda23f1c0f84118c50131313107f3fb5ad524f541d4c51c631f79aa45626fe1535d0c0a4b10479c3cdf7d0e61c5a35715ae05e0506cf48fcc12214528e337818252c58bd3aba0ac055ce1ea7d380a79d3fdf55b33013d5d8153ef6f6491e656978d04c65cf53418abdf4ae67b5d3d7ee5216a0616bd25c5'
}
var cccccc2 = { 
    encrypt: '+LrEsdOwOIR76E8BgwoKt53FQHfo48Gq06cq3LXw8lbBgAQU7hJy5Ll4oSpwX2Es',
    sig: '6d053e0feb4930f867f495ffe9a6223b205070e60abd4192b2e8acfe1584eac034d3105c322f83ab6d2a41a8276c711679c712eade8da63941e5915d8cfee6213e255d0a303c50d441ea0941bb97e1737f7aec66ffe2efe3e8991722960a2af7c08a81188b9cc3e485816dc2cbfb91e7508733ab8e52348e39b45714c40d0812'
}
var cccccc = { 
    encrypt: 'sT93ryiue3k3Q9mXKeXz4rRz2zzfMqldQ7sA4HIz6Ea8xG8vXvOtjr02HvoYth33',
    sig: '5ea2ce4f9c2ac090fb0511aa6d38d25746ed7690d448f0254adedc9c5091bef189f1fd99d616147f3f7a388bf4672862ee0841d75eec6c31c845b29adfdbba17976dc4a12e602075bebbcb9323641f0e05e169673b3cb28791f6a5ba198f03941bbb79920ab26d304688079eb75207646a11b01b9aa8e98bca52c220acba712b'
}


function content(c) {
    var key;
    if (c == "public")
        key = publicPem.toString();
    else if (c == "private")
        key = privatePem.toString();
    return key;
}

function decode_rsa_verify(data, sig) {
    var verify = crypto.createVerify('RSA-SHA256');
    verify.update(data);
    return verify.verify(content("public"), sig, 'hex');
}
var decrypt = function (crypted) {
    var key = "www.sxzd365.com_";//content("public");
    key = key.toString('hex');
    var iv = "1234567890abcdef";
    crypted = new Buffer(crypted, 'base64').toString('binary');
    var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
    var decoded = decipher.update(crypted, 'binary', 'utf8');
    decoded += decipher.final('utf8');
    return decoded;
};
//sig 签名
function decode_Connect(encrypt_str, sig) {
    var c = null;
    var ret = decode_rsa_verify(encrypt_str, sig);
    if (ret) {
        c = decrypt(encrypt_str);
    }
    return c;
}
CRC.CRC16 = function (buffer) {
    var hi = 0xff;
    var lo = 0xff;
    for (var i = 0; i < buffer.length; i++) {
        var idx = hi ^ buffer[i];
        hi = (lo ^ CRC._auchCRCHi[idx]);
        lo = CRC._auchCRCLo[idx];
    }
    var hx = 0;
    hx = hi << 8 | lo;
    return hx;
    //return CRC.padLeft((hi << 8 | lo).toString(16).toUpperCase(), 4, '0');
};

CRC.isArray = function (arr) {
    return Object.prototype.toString.call(arr) === '[object Array]';
};

CRC.ToCRC16 = function (str) {
    return CRC.CRC16(CRC.isArray(str) ? str : CRC.strToByte(str));
};

CRC.ToModbusCRC16 = function (str) {
    return CRC.CRC16(CRC.isArray(str) ? str : CRC.strToHex(str));
};

CRC.strToByte = function (str) {
    var tmp = str.split(''), arr = [];
    for (var i = 0, c = tmp.length; i < c; i++) {
        var j = encodeURI(tmp[i]);
        if (j.length == 1) {
            arr.push(j.charCodeAt());
        } else {
            var b = j.split('%');
            for (var m = 1; m < b.length; m++) {
                arr.push(parseInt('0x' + b[m]));
            }
        }
    }
    return arr;
};

CRC.convertChinese = function (str) {
    var tmp = str.split(''), arr = [];
    for (var i = 0, c = tmp.length; i < c; i++) {
        var s = tmp[i].charCodeAt();
        if (s <= 0 || s >= 127) {
            arr.push(s.toString(16));
        }
        else {
            arr.push(tmp[i]);
        }
    }
    return arr;
};

CRC.filterChinese = function (str) {
    var tmp = str.split(''), arr = [];
    for (var i = 0, c = tmp.length; i < c; i++) {
        var s = tmp[i].charCodeAt();
        if (s > 0 && s < 127) {
            arr.push(tmp[i]);
        }
    }
    return arr;
};

CRC.strToHex = function (hex, isFilterChinese) {
    hex = isFilterChinese ? CRC.filterChinese(hex).join('') : CRC.convertChinese(hex).join('');

    //清除所有空格
    hex = hex.replace(/\s/g, "");
    //若字符个数为奇数，补一个空格
    hex += hex.length % 2 != 0 ? " " : "";

    var c = hex.length / 2, arr = [];
    for (var i = 0; i < c; i++) {
        arr.push(parseInt(hex.substr(i * 2, 2), 16));
    }
    return arr;
};

CRC.padLeft = function (s, w, pc) {
    if (pc == undefined) {
        pc = '0';
    }
    for (var i = 0, c = w - s.length; i < c; i++) {
        s = pc + s;
    }
    return s;
};


function GetCrc16(buffer) {
    return CRC.ToCRC16(buffer);
}
function GetCrc16Hi(x) {
    return x >> 8;
}
function GetCrc16Lw(x) {
    return x & 0xff;
}



Date.prototype.Format = function (fmt) { //author: meizz 
    var o = {
        "M+": this.getMonth() + 1, //月份 
        "d+": this.getDate(), //日 
        "h+": this.getHours(), //小时 
        "m+": this.getMinutes(), //分 
        "s+": this.getSeconds(), //秒 
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度 
        "S": this.getMilliseconds() //毫秒 
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}
//写sensor传感器的指令保存
var read_col_cycle = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x31, 0x00, 0x01, 0xb7, 0x84, 0x16];     //读取采集间隔时间
var read_signal = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x58, 0x00, 0x01, 0x67, 0x98, 0x16];     //读取信号强度 ]
var read_mobile = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x59, 0x00, 0x03, 0xb7, 0x99, 0x16];     //手机号码
var read_punit = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x32, 0x00, 0x01, 0x47, 0x84, 0x16];     //读取压力单位
var read_lvalue = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x34, 0x00, 0x02, 0xe7, 0x84, 0x16];     //读取最小量程
var read_bvalue = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00, 0x02, 0x46, 0x44, 0x16];     //读取最大量程
var read_down = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x50, 0x00, 0x02, 0xa6, 0x5b, 0x16];     //读取报警下限
var read_up = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x52, 0x00, 0x02, 0x07, 0x9b, 0x16];     //读取报警上限 ]
var read_vol = [0x69, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x54, 0x00, 0x02, 0xE7, 0x9A, 0x16];     //读取电池电压 
var read_info_all = [read_col_cycle, read_signal, read_mobile, read_punit, read_lvalue, read_bvalue, read_down, read_up, read_vol];
var read_info = {
    "col_cycle": read_col_cycle
    , "signal": read_signal
    , "mobile": read_mobile
    , "punit": read_punit
    , "lvalue": read_lvalue
    , "bvalue": read_bvalue
    , "down": read_down
    , "up": read_up
    , "vol": read_vol
};


var write1_col_cycle = [0x69, 0x00, 0x01, 0x00, 0x01, 0x06, 0x00, 0x31, 0x00, 0x32, 0x3b, 0x91, 0x16];    //写入采集间隔时间50S   ok 
//69 00 01 00 01 06 00 31 00 32 3B 91 16    //指令原样回传 
var write_warn_down = [0x69, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x50, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x67, 0x16];   //修改报警下限  0   OK
//69 00 01 00 01 10 00 50 00 02 23 98 16                  //报警下限回传指令  
var write_warn_up = [0x69, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x52, 0x00, 0x02, 0x04, 0x44, 0x7A, 0x00, 0x00, 0xaf, 0x97, 0x16];   //修改报警上限  1000  OK
//69 00 01 00 01 10 00 52 00 02 82 58 16                  //报警下限回传指令 
var write_AH_AL = [0x69, 0x00, 0x01, 0x00, 0x01, 0x06, 0x00, 0x54, 0x00, 0x00, 0xaa, 0x5b, 0x16];//    //保存AH  AL  报警上限下限参数 OK
//69 00 01 00 01 06 00 54 00 01 6B 9B 16    //指令原样回传 
var write_phone = [0x69, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x40, 0x00, 0x06, 0x0C, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0xE1, 0x16];

var deviceid_socket = {};

function Str2Bytes(str) {
    var pos = 0;
    var len = str.length;
    if (len % 2 != 0) {
        return null;
    }
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i < len; i++) {
        var s = str.substr(pos, 2);
        var v = parseInt(s, 16);
        hexA.push(v);
        pos += 2;
    }
    return hexA;
}

function setdeviceid(id, buf_target) {
    //id传入的是字符串
    var x = Str2Bytes(id);
    var bx = Buffer.from(x);
    bx.copy(buf_target, 1, 0, 4);
}
function setcrc16(buf_target) {
    var len = buf_target.length;
    if (len < 5)
        return false;
    var copybuf = [];
    for (var i = 0; i < len - 3 ; i++) {
        copybuf.push(buf_target[i]);
    }
    var ret = GetCrc16(copybuf);
    var hiret = ret >> 8;
    var loret = ret & 0xff;
    //低字节赋值
    buf_target[len - 1 - 1] = loret;
    //高字节赋值
    buf_target[len - 1 - 2] = hiret;
}

function send_Read_infoAll(num, id, socket) {
    var data = read_info_all[num];
    if (data == null) {
        console.log("error!no flag of %s", flag);
        return;
    }
    var buf_temp = Buffer.from(data);

    setdeviceid(id, buf_temp);
    setcrc16(buf_temp);
    socket.write(buf_temp);
}

function sendWrite(id, flag, v, socket) {
    var buf_temp;
    var v_temp;
    if (flag == "col_cycle") {
        buf_temp = Buffer.from(write1_col_cycle);
        v_temp = parseInt(v);
        buf_temp.writeInt16BE(v_temp, 8);
    }
    else if (flag == "warn_up") {
        buf_temp = Buffer.from(write_warn_up);
        v_temp = parseFloat(v);
        buf_temp.writeFloatBE(v_temp, 11);
    }
    else if (flag == "warn_down") {
        buf_temp = Buffer.from(write_warn_down);
        v_temp = parseFloat(v);
        buf_temp.writeFloatBE(v_temp, 11);
    }
    else if (flag == "phonenumber1") {
        buf_temp = Buffer.from(write_phone);
        buf_temp[11] = 0x00;
        for (var i = 0; i < 11; i++) {
            //从12字节开始是电话号码
            buf_temp[i + 12] = v.charAt(i);
        }
    }
    else if (flag == "phonenumber2") {
        buf_temp = Buffer.from(write_phone);
        buf_temp[11] = 0x01;
        for (var i = 0; i < 11; i++) {
            //从12字节开始是电话号码
            buf_temp[i + 12] = v.charAt(i);
        }
    }
    else if (flag == "phonenumber3") {
        buf_temp = Buffer.from(write_phone);
        buf_temp[11] = 0x02;
        for (var i = 0; i < 11; i++) {
            //从12字节开始是电话号码
            buf_temp[i + 12] = v.charAt(i);
        }
    }
    else if (flag == "phonenumber4") {
        buf_temp = Buffer.from(write_phone);
        buf_temp[11] = 0x03;
        for (var i = 0; i < 11; i++) {
            //从12字节开始是电话号码
            buf_temp[i + 12] = v.charAt(i);
        }
    }
    else if (flag == "phonenumber5") {
        buf_temp = Buffer.from(write_phone);
        buf_temp[11] = 0x04;
        for (var i = 0; i < 11; i++) {
            //从12字节开始是电话号码
            buf_temp[i + 12] = v.charAt(i);
        }
    }
    else if (flag == "alahsave") {
        buf_temp = Buffer.from(write_AH_AL)
    }
    else {
        console.log("command is error");
        return;
    }
    setdeviceid(id, buf_temp);
    //设置crc16
    setcrc16(buf_temp);
    socket.write(buf_temp);
}
//st数组 len是数组的长度
function time_func_write(st, len, deviceid, socket) {
    var interval = 500;
    //read_time++;
    var t = len - 1;
    if (t == -1)
        return;
    setTimeout(function () {
        sendWrite(deviceid, st[t].flag, st[t].value, socket);
        time_func_write(st, t, deviceid, socket);
    }, interval);//
}
function time_func_write2(st, pos, len, deviceid, socket) {
    var interval = 1000;
    //read_time++;
    pos++;
    if (pos == len + 1)
        return;
    setTimeout(function () {
        sendWrite(deviceid, st[pos - 1].flag, st[pos - 1].value, socket);
        time_func_write2(st, pos, len, deviceid, socket);
    }, interval);//
}
function send2Sensor_write0(data) {
    var obj = deviceid_socket[data.deviceid];
    if (obj == null)
        return;
    var socket = obj.sock;
    if (socket == null) {
        console.log("not online deviceid %s", data.deviceid);
        return;
    }
    //保存所有的写命令
    obj.data = data;

}
function send2Sensor_write(data) {

    var st = [];
    if (data.deviceid == null || data.deviceid == "") {
        return;
    }
    //console.log("send2Sensor:");
    var obj = deviceid_socket[data.deviceid];
    if (obj == null)
        return;
    var socket = obj.sock;
    if (socket == null) {
        console.log("not online deviceid %s", data.deviceid);
        return;
    }
    //保存所有的写命令
    obj.data = data;
    //obj.time = new Date().getTime();
    obj.nwrite = 0; //要写的数据的个数
    obj.nwrite_ret = 0; //写数据回送了几次
    if (obj.online == 0) {
        console.log("not on line %s", data.deviceid);
        return;
    }
    //id是字符串
    //st.id = data.deviceid;
    //var timeout = 500;
    if (data.col_cycle != null) {
        obj.nwrite++; //要写的数据的个数
        var o1 = {};
        //o1.id = data.deviceid;
        o1.flag = "col_cycle";
        o1.value = data.col_cycle;
        //o1.sock = socket;
        st.push(o1);
    }

    var sendah = false;
    if (data.warn_up != null && data.warn_up != "") {
        obj.nwrite++; //要写的数据的个数
        sendah = true;
        var o = {};
        o.flag = "warn_up";
        o.value = data.warn_up;
        st.push(o);
    }
    if (data.warn_down != null && data.warn_down != '') {
        sendah = true;
        obj.nwrite++; //要写的数据的个数
        var o = {};
        o.flag = "warn_down";
        o.value = data.warn_down;
        st.push(o);
    }
    // sendah = false; //这里要去掉
    if (sendah == true) {
        obj.nwrite++; //要写的数据的个数
        var o = {};
        o.flag = "alahsave";
        o.value = 0;//data.warn_up;
        st.push(o);
    }
    if (data.phonenumber1 != null) {
        var str = "";
        str += data.phonenumber1;
        if (str.length < 11) {
            console.log("error phonenumber1 is not right!:%s", str);
        }
        else {

            console.log("the phone number is %s %d", str, str.length);
            obj.nwrite++; //要写的数据的个数
            var o = {};
            o.flag = "phonenumber1";
            o.value = str;
            st.push(o);
        }
    }
    if (data.phonenumber2 != null) {
        var str = "";
        str += data.phonenumber2;
        if (str.length < 11) {
            console.log("error phonenumber1 is not right!:%s", str);
        }
        else {
            obj.nwrite++; //要写的数据的个数
            var o = {};
            o.flag = "phonenumber2";
            o.value = str;
            st.push(o);
        }
    }
    if (data.phonenumber3 != null) {
        var str = "";
        str += data.phonenumber3;
        if (str.length < 11) {
            console.log("error phonenumber1 is not right!:%s", str);
        }
        else {
            obj.nwrite++; //要写的数据的个数
            var o = {};
            o.flag = "phonenumber3";
            o.value = str;
            st.push(o);
        }
    }
    if (data.phonenumber4 != null) {
        var str = "";
        str += data.phonenumber4;
        if (str.length < 11) {
            console.log("error phonenumber1 is not right!:%s", data.phonenumber4);
        }
        else {
            obj.nwrite++; //要写的数据的个数
            var o = {};
            o.flag = "phonenumber4";
            o.value = str;
            st.push(o);
        }
    }
    if (data.phonenumber5 != null) {
        var str = "";
        str += data.phonenumber5;
        if (str.length < 11) {
            console.log("error phonenumber1 is not right!:%s", str);
        }
        else {
            obj.nwrite++; //要写的数据的个数
            var o = {};
            o.flag = "phonenumber5";
            o.value = str;
            st.push(o);
        }
    }
    time_func_write2(st, 0, st.length, data.deviceid, socket);
}
function time_func_ask(deviceid, socket, readtime) {
    var interval = 500;
    //read_time++;
    setTimeout(function () {
        send_Read_infoAll(readtime, deviceid, socket);
        var xread = readtime - 1;
        if (xread == -1)
            return;
        time_func_ask(deviceid, socket, xread);
    }, interval);//
}
function send2sensor_ask(deviceid) {
    if (deviceid == null) {
        return;
    }
    //var deviceid = data.deviceid;

    var obj = deviceid_socket[deviceid];
    if (obj == null) {
        console.log("no socket here");
        return;
    }

    if (obj.online == 1) { //在线
        //console.log("ask the data");
        time_func_ask(deviceid, obj.sock, 8);
    }
}

function ProcessTcpServer(callback) {
    var server = net.createServer();
    //接受新的客户端连接  
    server.on('connection', function (socket) {
        //socket.manager.transports[socket.id].socket.setTimeout(25000);
        var v_deviceid = null;
        var port = socket.remotePort;
        var addr = socket.remoteAddress;

        console.log('CONNECTED: ' + socket.remoteAddress + ':' + socket.remotePort);
        //sockets.push(socket);
        //缓冲区 512字节
        var buf = Buffer.allocUnsafe(512);
        //缓存中的数据长度
        var buf_datasize = 0;

        //得到保存的对象
        function sock_obj() {
            if (v_deviceid == null)
                return null;
            return deviceid_socket[v_deviceid];
        }
        //69 00 01 00 01 04 08 46 7A 0B E8 41 F1 00 00 B2 87 16      // 压力16000  +  温度30.1 
        function device_offline() { //设备下线
            if (v_deviceid != null) {
                if (callback != null)
                    callback(null,{ deviceid: v_deviceid, status: 0 });
                var obj = sock_obj();
                if (obj != null)
                    obj.online = 0;
            }
        }
        function device_online() {
            if (v_deviceid != null) {
                if (callback != null)
                    callback(null, { deviceid: v_deviceid, status: 1 });
                var obj = sock_obj();
                if (obj != null)
                    obj.online = 0;
            }
        }
        function process_packet_cmd04(buff, pos, len) {
            //注意toString 1-5,是取四个字节
            v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            //console.log(buff);
            var v_press = buff.readFloatBE(pos + 7);
            v_press = v_press.toFixed(1);
            var v_temp = buff.readFloatBE(pos + 11);
            v_temp = v_temp.toFixed(1);
            var v_extern = null; //扩展8字节
            if (len - 10 == 0x10){ //后面还有扩展字节 2017/10/23日,减去头部尾部10字节，剩余16字节
            
                var e_vol = buff.readFloatBE(pos+15);//电压 四字节
                e_vol = e_vol.toFixed(1);//保留1字节
                var e_ct = buff.readInt16BE(pos+19);////采集时间 两个字节
                var e_sn  = buff[21];//信号强度 1字节
                var npa   = buff[22];//压力单位 00 pa 01 Hpa 02 Kpa 03 Mpa  1字节
                var e_pa = "pa";
                if (npa == 0)
                    e_pa = "pa";
                else if (npa == 1)
                    e_pa = "Hpa";
                else if (npa == 2)
                    e_pa = "Kpa";
                else if (npa == 3)
                    e_pa = "Mpa";
                else if (npa == 7)
                    e_pa = "mH20";
                v_extern = { vol: e_vol, col_cycle: e_ct, signal: e_sn, press_unit: e_pa };
            }
            device_online();
            //sock保存，是否在线，data，需要写的数据是否存在
            var obj = deviceid_socket[v_deviceid];


            if (obj == null) {
                deviceid_socket[v_deviceid] = {
                    sock: socket,
                    deviceid: v_deviceid,
                    online: 1,
                    data: null,
                    nwrite: 0,      //要写的数据的个数
                    nwrite_ret: 0, //写数据回送了几次
                    querytime: new Date().getTime(),
                    query_info: 1   //是否询问信息
                };
                obj = sock_obj();
            }
            else {
                obj.online = 1;
                obj.sock = socket; //保存socket
                if (obj.data != null) {
                    //调用发送函数
                    send2Sensor_write(obj.data);
                    //写回到界面显示
                    var vvtemp = {};
                    vvtemp.deviceid = v_deviceid;
                    if (obj.data.col_cycle != null) {
                        vvtemp.col_cycle = obj.data.col_cycle;
                    }
                    if (obj.data.warn_up != null) {
                        vvtemp.warn_up = obj.data.warn_up;
                    }
                    if (obj.data.warn_down != null) {
                        vvtemp.warn_down = obj.data.warn_down;
                    }
                    if (callback != null) {
                        callback(null, vvtemp);
                    }
                }
                var t2 = new Date().getTime();
                var t_diff = t2 - obj.querytime;
                if (t_diff > 1000 * 60 * 60 * 5) { //大于5个小时
                    obj.querytime = t2;
                    obj.query_info = 1;
                }
            }

            if (obj.query_info == 1) {
                //console.log("want first read");
                obj.query_info = 0;
                send2sensor_ask(v_deviceid);
            }
           
            var v_time = new Date().Format('yyyy-MM-dd hh:mm:ss');
            var data_1 = null;
            var data_extern = null;
            data_1 = {
                temp: v_temp,
                deviceid: v_deviceid,
                press: v_press,
                time: v_time
            }

            if (v_extern != null) {
                data_extern = {
                    deviceid: v_deviceid,
                    col_cycle: v_extern.col_cycle,
                    signal : v_extern.signal,
                    vol: v_extern.vol,
                    press_unit: v_extern.press_unit
                    };
            }
            
            //console.log(data_1);
            //data_1 是数据,存储到数据库, data_extern是扩展数据
            if (callback != null)
                callback(data_1,data_extern);
        }
        function process_packet_cmd03(buff, pos, len) {
            console.log("receive the cmd 0x03,not ok");
            return 0;
        }
        function process_packet_cmd06(buff, pos, len) {
            //采集间隔时间上传返回
            var obj = sock_obj();
            if (obj != null) {
                obj.nwrite_ret++;
            }
            if (obj.nwrite_ret == obj.nwrite) { //所有指令返回，写成功
                obj.data = null;
                obj.nwrite = 0;
                obj.nwrite_ret = 0;
                console.log("指令返回成功");
            }
        }
        function process_packet_cmd10(buff, pos, len) {
            //上下限返回,报警手机返回
            var obj = sock_obj();
            if (obj != null) {
                obj.nwrite_ret++;
            }
            if (obj.nwrite_ret == obj.nwrite) {//所有指令返回，写成功
                obj.data = null;
                obj.nwrite = 0;
                obj.nwrite_ret = 0;
                console.log("指令返回成功");
            }
        }
        //采集周期
        function process_packet_cmd13(buff, pos, len) {
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var time = buff.readInt16BE(pos + 7);
            if (callback != null) {
               // console.log("%s采集时间 : %d",v_deviceid, time);
                callback(null,{ deviceid: v_deviceid, col_cycle: time });
            }
            return 0;
        }
        //69 00 01 00 01 23 02 00 02 C5 E7 16        //2=kpa压力单位 
        function process_packet_cmd23(buff, pos, len) {
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var unit_1 = buff.readInt16BE(pos + 7);
            //console.log("receive the unit is %d", unit);
            var unit_int = parseInt(unit_1);
            if (callback != null) {
                var unit_str = "pa";
                switch (unit_int) {
                    case 1:
                        unit_str = "Hpa"
                        break;
                    case 2:
                        unit_str = "Kpa";
                        break;
                    case 3:
                        unit_str = "Mpa";
                        break;
                    case 7:
                        unit_str = "mH20";
                        break;

                }
                //var unit_str = unit_int == 0 ? "pa" : "kpa";
                callback(null,{ deviceid: v_deviceid, press_unit: unit_str });
            }
            return 0;
        }
        //69 00 01 00 01 33 04 00 00 00 00 3A DA 16   //最小量程
        function process_packet_cmd33(buff, pos, len) {
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var lvalue = buff.readFloatBE(pos + 7);
            //console.log("最小量程:%d", lvalue);
            if (callback != null)
                callback(null,{ deviceid: v_deviceid, minvalue: lvalue });
            return 0;
        }
        //69 00 01 00 01 43 04 44 7A 00 00 0F F3 16   //最大量程
        function process_packet_cmd43(buff, pos, len) {
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var bvalue = buff.readFloatBE(pos + 7);
            //console.log("最大量程:%d", bvalue);
            if (callback != null)
                callback(null, { deviceid: v_deviceid, maxvalue: bvalue });
            return 0;
        }
        //69 00 01 00 01 53 04 00 00 00 00 3A DA 16   //报警下限 
        function process_packet_cmd53(buff, pos, len) {
            //config_read_sensor.down = buff.readInt32BE(pos + 7); 
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var value = buff.readFloatBE(pos + 7);
            //console.log("报警下限:%d", value);

            if (callback != null)
                callback(null, { deviceid: v_deviceid, warn_down: value });
            return 0;
        }
        //69 00 01 00 01 63 04 40 80 00 00 2E F2 16    //报警上限 
        function process_packet_cmd63(buff, pos, len) {
            //config_read_sensor.up = buff.readInt32BE(pos + 7);
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var value = buff.readFloatBE(pos + 7);
             //console.log("报警上限:%d", value);

            if (callback != null)
                callback(null, { deviceid: v_deviceid, warn_up: value });

            return 0;
        }
        //69 00 01 00 01 73 04 45 4E 40 00 7E 01 16    //回复指令 电池电压 
        function process_packet_cmd73(buff, pos, len) {
            //config_read_sensor.vol = buff.readInt32BE(pos + 7);
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var value = buff.readFloatBE(pos + 7)
             //console.log("电池电压:%d", value);

            if (callback != null)
                callback(null, { deviceid: v_deviceid, vol: value });

            return 0;
        }
        //69 00 01 00 01 83 06 15 31 92 63 76 00 35 3C 16//读取SIM 号码  
        function process_packet_cmd83(buff, pos, len) { //sim卡号码
            //six bytes
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var str = buf.toString('hex', pos + 7, pos + 7 + 6);
            if (str.length > 11)
                str = str.substring(0, 11);
            //console.log("电话号码:%s", str);


            if (callback != null)
                callback(null, { deviceid: v_deviceid, sim: str });

            return 0;
        }
        //69 00 01 00 01 93 02 00 00 44 26 16        //值0读取信号强度 
        function process_packet_cmd93(buff, pos, len) {//读取信号强度
            var v_deviceid = buff.toString('hex', pos + 1, pos + 5);
            var value = buff.readInt16BE(pos + 7);
            //console.log("信号强度:%d", value);
            if (callback != null)
                callback(null, { deviceid: v_deviceid, signal: value });
            return 0;
        }
        function process_packet_cmd(cmd, data, pos, len) {
            switch (cmd) {
                case 0x03:
                    break;
                case 0x04:
                    return process_packet_cmd04(data, pos, len);
                case 0x06:
                    return process_packet_cmd06(data, pos, len);
                case 0x10:
                    return process_packet_cmd10(data, pos, len);
                case 0x13:
                    return process_packet_cmd13(data, pos, len);
                case 0x23:
                    return process_packet_cmd23(data, pos, len);
                case 0x33:
                    return process_packet_cmd33(data, pos, len);
                case 0x43:
                    return process_packet_cmd43(data, pos, len);
                case 0x53:
                    return process_packet_cmd53(data, pos, len);
                case 0x63:
                    return process_packet_cmd63(data, pos, len);
                case 0x73:
                    return process_packet_cmd73(data, pos, len);
                case 0x83:
                    return process_packet_cmd83(data, pos, len);
                case 0x93:
                    return process_packet_cmd93(data, pos, len);
            }
        }
        function process_packet_print(buff, pos, len) {
            //const buftemp = Buffer.from(buff, pos, len);
            var buftemp = Buffer.allocUnsafe(len);
            buff.copy(buftemp, 0, pos, pos + len);
            //console.log(buftemp.toString('hex'));
        }
        function process_packet_1(data, startpos, len) {
            //存数据库
            // console.log("startend is %x %x", data[startpos], data[startpos + len - 1]);
            if (data[startpos] != 0x69 ) {
                console.log("error packet");
                return -1;
            }
            //console.log(data);
            //  console.log("the cmd is %d", data[startpos + 5]);
            var cmd = data[startpos + 5];
            process_packet_cmd(cmd, data, startpos, len);
        }
        function process_packet_compelete(buff) {
            //  console.log("process_packet_compelete %d", buf_datasize);
            var startpos = 0;
            var packet_len = 0;
            //var packet_len =  7 + 3 + buff[6+startpos];
            while (true) {
                if (buf_datasize >= 7) {
                    packet_len = 7 + 3 + buff[6 + startpos];
                    //console.log("packet_len %d", packet_len);
                }
                else {
                    //console.log("buf_datasize<7");
                    if (buf_datasize == 0)
                        return 0;
                    return startpos;
                }
                if (buf_datasize >= packet_len) {
                    //console.log("now buf_datasize %d packet_len %d startpos %d", buf_datasize, packet_len,startpos);
                    process_packet_1(buf, startpos, packet_len);
                    buf_datasize -= packet_len;
                    startpos += packet_len;

                }
                else {
                    if (buf_datasize == 0)
                        return 0;
                    return startpos;
                }
            }
        }
        //处理包
        function process_packet(data) {
            //把数据拷贝到buf之后
           // console.log("receive data :%d", data.length);
            data.copy(buf, buf_datasize);
            buf_datasize += data.length;
            //  console.log("now recv length " + buf_datasize);
            if (buf_datasize < 7) {//不够包头的长度，继续接收
                return;
            }
            var startpos = process_packet_compelete(buf);
            if (startpos != 0) {
                buf.copy(buf, 0, startpos, startpos + buf_datasize);
            }

        }
        socket.on('data', function (data) {
            process_packet(data);
        });
        socket.on('close', function () {
            //将id状态改为不在线
            console.log('close: ' + socket.remoteAddress + ' ' + socket.remotePort);
            device_offline();
            //var index = sockets.indexOf(socket);
            //sockets.splice(index, 1);
        });
        socket.on('error', function (err) {
            console.log('socket error:' + err);
            socket.end();
            device_offline();
        });
        socket.on('end', function () {
            console.log('client disconnected');
            device_offline();
        });
    });
    server.on('close', function () {
        console.log('Server closed');
    });

    server.listen(8051);

}






function post_data(obj, options, token, cb) {
    var content = JSON.stringify(obj);
    var jsonheaders = {
        'Content-Type': 'application/json',
        'Content-Length': content.length,
    };
    options.headers = jsonheaders;
    var req = http.request(options, function (res) {
        res.setEncoding('utf8');
        if (res.statusCode == 200) {
            var body = "";
            res.on('data', function (data) {
                body += data;
            });
            res.on('end', function () {
                if (cb != null)
                    cb(200, body);
            });
        }
        else {
            if (cb != null)
                cb(500, -1);
        }
    });

    req.on('error', function (e) {
        console.log('problem with request: ' + e.message);
        if (cb != null) {
            // cb(-1,e.message);
        }
    });

    req.write(content);
    req.end();
}

//16字节包含crc和头部长度
//protocol 协议 callback  回调函数; 
function parseurl(urlpath) {
    if (urlpath == null)
        return null;
    var ret = url.parse(urlpath);
    var options = {};
    options.hostname = ret.hostname;
    options.port = ret.port;
    options.path = ret.path;
    options.method = "POST";
    return options;
}

var connect_str = null;
var connect_option = null;
function callback(data, data_ext) {

    if (connect_option == null || connect_str == null) {
        connect_str = decode_Connect(cccccc.encrypt, cccccc.sig);
        connect_option = parseurl(connect_str);
    }
    var rd = { data: data, data_ext: data_ext };
    console.log(rd);
    post_data(rd, connect_option, null, null);
}


function callback_udp(data) {
    var obj = JSON.parse(data);
    console.log("send to sensor:", obj);
    if (obj.deviceid == null)
        return;
    var deviceid = obj.deviceid;
    if (obj.cmd == "write") {
        var obj_w = {};
        obj_w.col_cycle = obj.col_cycle;
        obj_w.warn_up = obj.warn_up;
        obj_w.warn_down = obj.warn_down;
        obj_w.deviceid = deviceid;
        send2Sensor_write0(obj);
    }
    else if (obj.cmd == "read") {
        send2sensor_ask(obj.deiveid)
    }
}



function ProcessUdpServer(callback) {

    var server = dgram.createSocket('udp4');
    server.on('error', function (err) {
        console.log("udp server error:\n", err);
        server.close();
    });

    server.on('message', function (msg) {
        console.log("server got: ", msg);
        if (msg != null) {
            if (callback != null) {
                callback(msg);
            }
        }
    });
    server.on('listening', function () {
        var address = server.address();
    });
    server.bind(8051);
}



function test() {
    var min = 20;
    var max = 25;
    var deviceid = parseInt(Math.random() * (50 - 1 + 1) + 1, 10);
    deviceid += ""
    data = {
        temp: parseInt(Math.random() * (max - min + 1) + min, 10),
        deviceid: "123456",
        press: parseInt(Math.random() * (50000 - 20000 + 1) + 50000, 10),
        time :new Date().Format('yyyy-MM-dd hh:mm:ss')
        //time: v_time
    };
    data_ext = {
        deviceid: "123456",
        col_cycle: 10,
        signal: 12,
        vol: 13,
        press_unit: "pa"
    };
    callback(data, data_ext);
    setTimeout(test, 1000*10);
}
ProcessTcpServer(callback);
ProcessUdpServer(callback_udp);
//test();
console.log("start server");
